package org.qdao;

import java.util.List;
/**
 * 
 * @author 譚元吉
 * @since 2010/02/06 11:00:50
 */
public interface IEntityDao<T> {
	List<?> script( final String script );
	/**
	 * 创建该表
	 * 
	 * @author tan
	 * @return 2010/03/03 10:23:14
	 */
	public boolean create();

	/**
	 * 删除表操作
	 * 
	 * @author tan
	 * @return 2010/03/03 10:23:21
	 */
	public boolean drop();

	/**
	 * 判断表是否存在
	 * 
	 * @author tan
	 * @return 2010/03/03 10:23:29
	 */
	public boolean exist();

	/**
	 * 插入一条记录
	 * 
	 * @author tan
	 * @param dto
	 * @return 2010/03/03 10:23:39
	 */
	public boolean insert(T dto);

	/**
	 * 插入多条记录
	 * 
	 * @author tan
	 * @param dtos
	 * @return 2010/03/03 10:23:47
	 */
	public boolean insert(List<?> dtos);

	/**
	 * 匹配表是否符合 EntityDao<T>中的 T
	 * 
	 * @author tan
	 * @param table
	 * @return 2010/03/03 10:23:57
	 */
	public boolean match(Class<? extends T> table);

	/**
	 * 通过主键查询一条记录
	 * 
	 * @author tan
	 * @param key
	 * @return 2010/03/03 10:24:33
	 */
	public T select(T key);

	/**
	 * SELECT ALL语句查询多条记录
	 * 
	 * @author tan
	 * @return 2010/03/03 10:24:50
	 */
	public List<T> select();

	public List<T> select(IFetchHandler<T> filter);

	/**
	 * 支持条件语句的 SELECT 语句
	 * 
	 * <pre>
	 * dao.select(&quot;1 = 1 AND 2 = 2&quot;);
	 * </pre>
	 * 
	 * @author tan
	 * @param sqlPart
	 * @return 2010/03/03 10:25:10
	 */
	public List<T> select(String sqlPart);

	public List<T> select(String sqlPart, IFetchHandler<T> filter);
	
	public List<T> selectNative(String sql);	
	
	/**
	 * 查询单列的内容 select id from t_life;  - > list(id)
	 * 查询对象内容 select * from t_life;   - > list(Life)
	 * @param sql
	 * @param isReturnEntityList isSingleColumn.
	 * @return
	 */
	List selectNative(final String sql, final boolean isReturnEntityList);
	
	
	/**
	 * 更新一条记录，主键不能改变
	 * 
	 * @author tan
	 * @param key
	 * @return 2010/03/03 10:15:07
	 */
	public T update(T key);

	/**
	 * 更新多条记录
	 * 
	 * @author tan
	 * @param key
	 * @return 2010/03/03 10:15:07
	 */
	public boolean update(List<T> data);

	/**
	 * 删除一条记录
	 * 
	 * @author tan
	 * @param key
	 * @return 2010/03/03 10:15:42
	 */
	public boolean delete(T key);

	/**
	 * 删除多条记录
	 * 
	 * @author tan
	 * @param data
	 * @return 2010/03/03 10:15:51
	 */
	public boolean delete(List<T> data);

	/**
	 * 通过条件删除记录
	 * 
	 * @author tan
	 * @param sqlPart
	 * @return 2010-3-7 下午10:44:36
	 */
	boolean deletePart(String sqlPart);

	/**
	 * <pre>
	 * 	lockModel is true : LOCK TABLE IN SHARE MODEL
	 *  lockModel is false: LOCK TABLE IN EXCLUSIVE MODEL
	 * </pre>
	 * 
	 * @author tan
	 * @param lockMode
	 * @return 2010/03/01 15:53:17
	 */
	public boolean lock(boolean lockMode);

	/**
	 * <pre>
	 * 零 背景:
	 *  数据库是一个多用户使用的共享资源。当多个用户并发的存取数据时，
	 *  在数据库中就回产生多个事务同时存取同一数据的情况。若对并发
	 *  操作不加控制可能会读取和存储不正确的数据，破坏数据库的一致性。
	 * 一  定义:
	 * 	加锁是实现数据库并发控制的一个非常重要的技术。
	 * 	当失误对某个数据对象进行操作之前, 先想系统发出请求，对其加锁。
	 * 	加锁后失误就对该数据对象有了一定的控制，在该失误释放锁之前，
	 * 	其他的失误不能对此数据对象进行更新操作
	 * 二 类型:
	 *  排他锁:(Exclusive Locks,X锁)数据对象被加上了排他锁时候，其他事务
	 *  不能对它读取和修改.
	 *  共享锁:(Share Locks,S锁)加了共享锁数据对象被其他事务读取，但不能
	 *  修改。
	 *  数据库利用这两种锁类型来对数据库的失误进行并发的控制.
	 *  
	 * 三 Oracle保护对象的不同,Oracle数据库锁分类:
	 * 	DML(Data locks, 数据锁),用于保护数据的完整性;
	 *  DDL(dictionary locks, 字典锁), 用于保护数据对象的结构，如表和索引等的定义
	 *  内部锁和闩(internal locks and latches) ,保护数据库的内部的结构,应用于SGA;
	 *  
	 *  开发中涉及最多的就是DML锁,其他两种的话DBA 会更加的关心;
	 * 四.DML锁
	 * 	DML锁目的在于保证并发情况下数据的完整性，主要包括:
	 * 	表级琐(TM锁)，事务锁或者行级琐(TX锁)
	 * 
	 * 	Oracle执行DMl语句的时候，系统自动的在索要的操作的表上申请TM类型的锁.当TM锁获得后
	 * ，系统再自动申请TX类型的锁，实际锁定的数据行的锁标志位进行位置。这样的失误加锁的检查
	 * TX锁的相容性时就不再逐行检查锁标志，只需要检查TM锁的模式的相容性即可，大大提高系统效率。
	 * TM锁包括了 SS, SX , S, X 等多种的模式，数据库中用0-6表示.不同的SQL操作产生不同的TM锁
	 * 五. 描述
	 * 	0 NONE
	 * 	1 NULL 空s
	 * 	2 SS(ROW-S) 行级共享锁 其他对象查询数据行 SELECT FOR UPDATE , LOCK FOR UPDATE, LOCK ROW SHARE
	 *  3 SX(ROW-X) 行级排他锁 提交前不允许做DML操作: INSERT , UPDATE, DELETE
	 *  4 S(SHARE) 共享锁  CREATE INDEX, LOCK SHARE
	 *  5 SSX(S/ROW-X) 共享行级排他锁 LOCK SHARE ROW EXCLUSIVE 
	 *  6 X (EXCLUSIVE) 排他锁 ALTER TABLE, DROP TABLE, DROP INDEX
	 *  TRUNCATE TABLE, LOCK EXCLUSIVE 
	 *  数据行行上只有X锁(排他锁) .在 Oracle 数据库中， 当一个事务首次发起一个DML语句时候就获得
	 *  一个TX锁，该锁保持到失误被提交或者回滚。当两个或者多个绘画在表的同一条记录上执行DML语句时，
	 *  第一个绘画在该条记录上加锁，其他的绘画处于等待状态。当第一个会话提交后，TX锁被释放,其他会话
	 *  才可以加锁
	 * 六. 几个问题
	 * 1. UPDATE/DELETE 操作会将RS锁定,直至commit或者rollback
	 * 	  若操作未COMMIT之前其他的 session 对同样的RS做变更操作,则操作会HOLD
	 * 	 直至前 session 的 update/delete 操作被commmit
	 * 2. session 内外 select 的 rs范围
	 *   前提: insert , update 操作未commit之前进行select
	 *   若在同一 session 内， select 出来的 rs 会包括之前的 insert , update 影响记录
	 *   若不在同一 session 内, select 出来的 rs 不会包括未被  commit的记录
	 * 3. select ... for update [OF cols] [NOWAIT/WAIT] [SKIP LOCKED]
	 *   OF cols: 锁定指定的字段所在表的 RS ，而没有指定表则不会锁定，只会在多表联合查询出现
	 *   NOWAIT： 语句不会 hold, 而直接返回错误 ORA-0005
	 * </pre>
	 * 
	 * @param timeout
	 *            wait seconds
	 */
	public boolean lock(int timeout);

	/**
	 * 锁定一条记录
	 * 
	 * @author tan
	 * @param key
	 * @return 2010/03/03 10:16:05
	 */
	public T lock(T key);

	/**
	 * 锁定一条记录,并且可以设置超时时间，单位为秒
	 * 
	 * @author tan
	 * @param key
	 * @param timeout
	 * @return 2010/03/03 10:16:18
	 */
	public T lock(T key, int timeout);

	/**
	 * 锁定多条记录，并且可以带上WHERE的条件语句
	 * 
	 * <pre>
	 * 例如: dao.lock(&quot;1 = 1&quot;);
	 * </pre>
	 * 
	 * @author tan
	 * @param sqlPart
	 * @return 2010/03/03 10:17:04
	 */
	public List<T> lock(String sqlPart);

	/**
	 * 锁定多条记录，并且可以带上WHERE的条件语句,可以设置超时 单位为秒
	 * 
	 * <pre>
	 * 例如: dao.lock(&quot;1 = 1&quot;);
	 * </pre>
	 * 
	 * @author tan
	 * @param sqlPart
	 * @return 2010/03/03 10:17:04
	 */
	public List<T> lock(String sqlPart, int timeout);

	/**
	 * 查询表中的记录的条数
	 * 
	 * <pre>
	 * 例如: 
	 * DBEngine engine = DBEngineFactory.getEngine(config);
	 * engine.initialize(config);
	 * EntityDao<?> dao = engine.getEntityDao(Cat.class);
	 * int count = dao.count();
	 * </pre>
	 * 
	 * @author tan
	 * @return 2010/03/03 10:19:13
	 */
	public Integer count();

	/**
	 * 查询表中的记录的条数
	 * 
	 * <pre>
	 * 例如: 
	 * DBEngine engine = DBEngineFactory.getEngine(config);
	 * engine.initialize(config);
	 * EntityDao<?> dao = engine.getEntityDao(Cat.class);
	 * int count = dao.count(&quot;1 = 1 AND 2 = 2&quot;);
	 * </pre>
	 * 
	 * @author tan
	 * @return 2010/03/03 10:19:13
	 */
	public Integer count(String sqlPart);

	/**
	 * <pre>
	 * if the arguments is true 
	 * then DROP by the key word
	 * "CASCADE CONSTRAINTS"
	 * yet the arguments is false 
	 * then drop the table like: drop table dog;
	 * </pre>
	 * 
	 * @author tan
	 * @param cascade
	 *            control the constraints
	 * @return 2010/02/26 15:49:28
	 */
	boolean drop(boolean cascade);
	
	
	boolean connect();
	
	T selectByPrimaryKey(Object ... objects );
}
